#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Author : gao
# Time : 2020/7/5 14:33

import numpy as np
import os
from sklearn import neighbors
from matplotlib import font_manager as fm, rcParams
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif']=['SimHei'] #显示中文标签
plt.rcParams['axes.unicode_minus']=False   #这两行需要手动设置

'''
    k近邻 sklearn版
    手写数字识别
'''

'''
    功能：从文件加载数据
    参数：
        filename : 文件名
    返回:
        dataSet : 数据集
        lables : 数据对应的标签
            
'''
def loadData(path):
    # 读取文件列表
    filesList = os.listdir(path=path)
    # 定义返回的矩阵
    dataSet = np.zeros((len(filesList), 32 * 32))  # 数据集是32*32 全部放在一列一行
    # 定义标签列表
    labels = []
    # 行数
    numLine = 0
    # 读取文件，存在矩阵里
    for f in filesList:
        with open(path + '/' + f) as fo:
            lines = fo.readlines()
            # 当前文件的数据列表，直接往里追加形成一列
            linesList = []
            for line in lines:
                # 去掉每行尾的换行符
                line = line.strip()
                for t in line:
                    linesList.append(t)
            dataSet[numLine] = linesList
            numLine += 1
            labels.append(f[0])
    return dataSet, labels


'''
    功能：获取kNN分类器
    参数：
        trainX : 训练数据
        trainY : 训练标签
        k : kNN的k
    返回：kNN分类器
'''
def getKNNModel(trainX, trainY, k):
    # 定义分类器
    clf = neighbors.KNeighborsClassifier(n_neighbors=k, weights='uniform', algorithm='auto')
    # 训练
    clf.fit(trainX, trainY)
    return clf


'''
    功能：测试kNN分类器
    参数：
        testX : 测试数据
        testY : 测试标签
    返回值：错误率
'''
def test(clf: neighbors.KNeighborsClassifier, testX, testY):
    # 总数
    total = len(testY)
    # 错误数
    error = 0

    i = 0
    for X in testX:
        predY = clf.predict([X])[0]
        if testY[i] != predY:
            error += 1
            #print('预测: ', predY, ',实际： ', testY[i])
        i += 1
    eRate =error / total
    print('错误率%.2f%%' % (eRate*100))
    return eRate

'''
    功能：画折线图
        
'''
def plot(x,y):


    plt.plot(x,y)
    plt.title('各个k值得错误率')
    plt.xlabel('k值')
    plt.ylabel('错误率')
    plt.show()


if __name__ == '__main__':
    pathTest = r'C:/Users/gao/Desktop/Machine-Learning-in-Action-master/Machine-Learning-in-Action-master/机器学习实战数据集/Ch02-KNN/testDigits'
    testX, testY = loadData(pathTest)
    pathTrain = r'C:/Users/gao/Desktop/Machine-Learning-in-Action-master/Machine-Learning-in-Action-master/机器学习实战数据集/Ch02-KNN/trainingDigits'
    trainX, trainY = loadData(pathTrain)
    elist = []
    endNum = input('请输入结束得k值:')
    for i in range(1,int(endNum)):
        print('k的值为： ',i,'________开始_________')
        clf = getKNNModel(trainX, trainY, i)
        e=test(clf, testX, testY)
        elist.append(e)
        print('k的值为： ',i,'________结束_________')
    plot(range(1,int(endNum)),elist)